﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Text;
using FRMS.Model;
using FRMS.BUS;

namespace FRMS.DAL
{
    public class ModbusRtu
    {

        #region CRC


        /// <summary>
        /// 计算CRC16TOData,返回数据串（原始校验数据+CRC校验结果）
        /// </summary>
        /// <param name="data"></param>
        /// <returns>高位在前</returns>
        public byte[] CRC16TOData(string data)
        {
            if ((data.Length % 2) != 0) { throw new Exception("参数\"data\"长度不合法"); }
            byte[] tmp = StrToByte(data);

            /*
            1、预置16位寄存器为十六进制FFFF（即全为1）。称此寄存器为CRC寄存器； 
            2、把第一个8位数据与16位CRC寄存器的低位相异或，把结果放于CRC寄存器； 
            3、把寄存器的内容右移一位(朝低位)，用0填补最高位，检查最低位； 
            4、如果最低位为0：重复第3步(再次移位); 如果最低位为1：CRC寄存器与多项式A001（1010 0000 0000 0001）进行异或； 
            5、重复步骤3和4，直到右移8次，这样整个8位数据全部进行了处理； 
            6、重复步骤2到步骤5，进行下一个8位数据的处理； 
            7、最后得到的CRC寄存器即为CRC码。
            */
            UInt16 CRCREG = (UInt16)0xffff;
            for (int i = 0; i < tmp.Length; i++)
            {
                CRCREG = (UInt16)(CRCREG ^ (UInt16)tmp[i]);//<< 8;
                for (int j = 0; j < 8; j++)
                {
                    UInt16 CRCtmp = (UInt16)(CRCREG & (UInt16)0x0001);
                    CRCREG = (UInt16)(CRCREG >> (UInt16)1);
                    if (CRCtmp == (UInt16)1)
                    {
                        CRCREG = (UInt16)(CRCREG ^ (UInt16)0xA001);
                    }
                }
            }

            string strtmp = CRCREG.ToString("X4");
            byte[] retunBtye = new byte[data.Length / 2 + 2];
            tmp.CopyTo(retunBtye, 0);
            retunBtye[data.Length / 2] = StrToByte(strtmp.Substring(2, 2))[0];
            retunBtye[data.Length / 2 + 1] = StrToByte(strtmp.Substring(0, 2))[0];
            //byte[] retunBtye = new byte[8];
            //tmp.CopyTo(retunBtye, 0);
            //retunBtye[6] = StrToByte(strtmp.Substring(2, 2))[0];
            //retunBtye[7] = StrToByte(strtmp.Substring(0, 2))[0];
            return retunBtye;
        }

        /// <summary>
        /// 字符转换
        /// </summary>
        public byte[] StrToByte(string data)
        {
            byte[] bt = new byte[data.Length / 2];
            for (int i = 0; i < data.Length / 2; i++)
            {
                bt[i] = Convert.ToByte(data.Substring(i * 2, 2), 16);
            }
            return bt;
        }

        //string dd = "010300000004";
        //byte[] fef = System.Text.Encoding.Default.GetBytes(dd);
        //byte[] jj = CRC16TOData(dd);
        //string data = ToHexs(jj, ""); data输出0103000000044409

        /// <summary>
        /// 转成十六进制输出）
        /// </summary>
        public static string ToHexs(byte[] data, string spit = ",")
        {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < data.Length; i++)
            {
                sb.Append(data[i].ToString("X2"));

                sb.Append(spit);
            }
            string str = sb.ToString();
            if (str.Equals("")) return "";
            return str = string.IsNullOrEmpty(spit) ? str : str.Substring(0, str.Length - 1);
        }

        /// <summary>
        /// 面板与电梯控制器心跳数据
        /// </summary>
        /// 
        public string GetheartbeatToDevices()
        {
            //string str = "010300000004";
            //byte[] jj = CRC16TOData(str);
            //string data = ToHexs(jj, "");
            string data = "0103000000044409";
            return data;
        }

        /// <summary>
        /// 生成前门内呼命令
        /// </summary>
        public string GetCallCmd(string Pfloor, string personid)
        {
            if (Pfloor == "")
            {
                return "";
            }
            else
            {
                string DefaultFloor = "";
                string updateFloorTOHex = "";
                string[] strArray = Pfloor.Split(',');
                string dd;
                for (int i = 1; i <= 80; i++)
                {
                    DefaultFloor = DefaultFloor + "0";
                }
                for (int j = 0; j < strArray.Length; j++)
                {

                    DefaultFloor = DefaultFloor.Remove(80 - Convert.ToInt32(strArray[j]), 1).Insert(80 - Convert.ToInt32(strArray[j]), "1");
                }
                string updateFloor = DefaultFloor.Substring(64, 16) + DefaultFloor.Substring(48, 16) + DefaultFloor.Substring(32, 16) + DefaultFloor.Substring(16, 16) + DefaultFloor.Substring(0, 16);
                for (int k = 0; k < 80; k += 8)
                {
                    updateFloorTOHex = updateFloorTOHex + string.Format("{0:X}", Convert.ToInt32(updateFloor.Substring(k, 8), 2)).PadLeft(2, '0');
                }
                if (strArray.Length > 1)
                {
                    //楼层数大于1个，则为内呼授权40016-40020
                    dd = "0111000F00050A" + updateFloorTOHex + personid.PadLeft(8, '0');
                }
                else
                {
                    //楼层数1个，则为点亮40026-40030
                    dd = "0111001900050A" + updateFloorTOHex + personid.PadLeft(8, '0');
                }
                byte[] jj = CRC16TOData(dd);
                string data = ToHexs(jj, "");
                return data;
            }
        }


        /// <summary>
        /// 生成前门内呼命令-带梯号
        /// </summary>
        public string GetCallCmdByLadderID(string Pfloor, string personid, int ladderid)
        {
            if (Pfloor == "")
            {
                return "";
            }
            else
            {
                string DefaultFloor = "";
                string updateFloorTOHex = "";
                string[] strArray = Pfloor.Split(',');
                string dd;
                for (int i = 1; i <= 80; i++)
                {
                    DefaultFloor = DefaultFloor + "0";
                }
                for (int j = 0; j < strArray.Length; j++)
                {

                    DefaultFloor = DefaultFloor.Remove(80 - Convert.ToInt32(strArray[j]), 1).Insert(80 - Convert.ToInt32(strArray[j]), "1");
                }
                string updateFloor = DefaultFloor.Substring(64, 16) + DefaultFloor.Substring(48, 16) + DefaultFloor.Substring(32, 16) + DefaultFloor.Substring(16, 16) + DefaultFloor.Substring(0, 16);
                for (int k = 0; k < 80; k += 8)
                {
                    updateFloorTOHex = updateFloorTOHex + string.Format("{0:X}", Convert.ToInt32(updateFloor.Substring(k, 8), 2)).PadLeft(2, '0');
                }
                if (strArray.Length > 1)
                {
                    //楼层数大于1个，则为内呼授权40016-40020
                    dd = ladderid.ToString("X").PadLeft(2, '0') + "11000F00050A" + updateFloorTOHex + personid.PadLeft(8, '0').Substring(0, 8);
                }
                else
                {
                    //楼层数1个，则为点亮40026-40030
                    dd = ladderid.ToString("X").PadLeft(2, '0') + "11001900050A" + updateFloorTOHex + personid.PadLeft(8, '0').Substring(0,8);
                }
                byte[] jj = CRC16TOData(dd);
                string data = ToHexs(jj, "");
                return data;
            }
        }



        /// <summary>
        /// 生成前门内呼命令-带梯号
        /// </summary>
        public string GetN71SPCallCmdByLadderID(string Pfloor, int ladderid)
        {
            if (Pfloor == "")
            {
                return "";
            }
            else
            {
                string DefaultFloor = "";
                string updateFloorTOHex = "";
                string[] strArray = Pfloor.Split(',');
                string dd;
                for (int i = 1; i <= 80; i++)
                {
                    DefaultFloor = DefaultFloor + "0";
                }
                for (int j = 0; j < strArray.Length; j++)
                {

                    DefaultFloor = DefaultFloor.Remove(80 - Convert.ToInt32(strArray[j]), 1).Insert(80 - Convert.ToInt32(strArray[j]), "1");
                }
                string updateFloor = DefaultFloor.Substring(64, 16) + DefaultFloor.Substring(48, 16) + DefaultFloor.Substring(32, 16) + DefaultFloor.Substring(16, 16) + DefaultFloor.Substring(0, 16);
                for (int k = 0; k < 80; k += 8)
                {
                    updateFloorTOHex = updateFloorTOHex + string.Format("{0:X}", Convert.ToInt32(updateFloor.Substring(k, 8), 2)).PadLeft(2, '0');
                }
                if (strArray.Length > 1)
                {
                    //楼层数大于1个，则为内呼授权40016-40020
                    dd = ladderid.ToString("X").PadLeft(2, '0') + "11000F00050A" + updateFloorTOHex;
                }
                else
                {
                    //楼层数1个，则为点亮40026-40030
                    dd = ladderid.ToString("X").PadLeft(2, '0') + "11001900050A" + updateFloorTOHex;
                }
                byte[] jj = CRC16TOData(dd);
                string data = ToHexs(jj, " ");
                return data;
            }
        }

        /// <summary>
        /// 物业管理员全楼层开放设定
        /// </summary>
        /// 
        public string GetCallAdminCmd(string personid)
        {
            string str = "011100370001020001" + personid.PadLeft(8, '0');// + dtime.ToString("X6").PadLeft(4, '0');
            byte[] jj = CRC16TOData(str);
            string data = ToHexs(jj, "");
            return data;
        }

        /// <summary>
        /// 物业管理员全楼层开放设定-带梯号
        /// </summary>
        /// 
        public string GetCallAdminCmdByLadderID(string personid, int ladderid)
        {
            string str = ladderid.ToString("X").PadLeft(2, '0') + "1100370001020001" + personid.PadLeft(8, '0');// + dtime.ToString("X6").PadLeft(4, '0');
            byte[] jj = CRC16TOData(str);
            string data = ToHexs(jj, " ");
            return data;
        }

        /// <summary>
        /// 物业管理员全楼层开放设定-带梯号
        /// </summary>
        /// 
        public string GetN71SPCallAdminCmdByLadderID(int ladderid)
        {
            string str = ladderid.ToString("X").PadLeft(2, '0') + "1100370001020001";
            byte[] jj = CRC16TOData(str);
            string data = ToHexs(jj, " ");
            return data;
        }

        /// <summary>
        /// 梯控状态设定,0 = 退出梯控，1 = 进入梯控
        /// </summary>
        /// 
        public string GetLiftStateCmd(int stateFlg)
        {
            string strstate = "";
            if (stateFlg == 0)
            {
                strstate = "00";
            }
            else
            {
                strstate = "01";
            }
            //int Intervaltime = Convert.ToInt32(CommVars.Configuration.GetSection("IntervalTime").Value);
            int Intervaltime = Convert.ToInt32(AppSettingsHelper.Configuration["IntervalTime"]);

            string str = "0110003800020400" + strstate + Convert.ToString(Intervaltime / 1000, 16).ToUpper().PadLeft(4, '0');//"0" + stateFlg.ToString();
            byte[] jj = CRC16TOData(str);
            string data = ToHexs(jj, "");
            return data;
        }

        /// <summary>
        /// 梯控状态设定,0 = 退出梯控，1 = 进入梯控
        /// </summary>
        /// 
        public string GetLiftStateCmdByLadderID(int stateFlg, int ladderid)
        {
            string strstate = "";
            if (stateFlg == 0)
            {
                strstate = "00";
            }
            else
            {
                strstate = "01";
            }
            //int Intervaltime = Convert.ToInt32(CommVars.Configuration.GetSection("IntervalTime").Value);
            int Intervaltime = Convert.ToInt32(AppSettingsHelper.Configuration["IntervalTime"]);

            string str = ladderid.ToString("X").PadLeft(2, '0') + "10003800020400" + strstate + Convert.ToString(Intervaltime / 1000, 16).ToUpper().PadLeft(4, '0');//"0" + stateFlg.ToString();
            byte[] jj = CRC16TOData(str);
            string data = ToHexs(jj, " ");
            return data;
        }

        public string GetN71SPheartbeat(string ladderid)
        {
            string str = ladderid.PadLeft(2, '0') + "0300000004";
            byte[] jj = CRC16TOData(str);
            string data = ToHexs(jj, " ");
            return data;
        }

        public string GetTKCmd(int ladderid, int mode)
        {
            string strstate = "";
            if (mode == 0)
            {
                strstate = "00";
            }
            else
            {
                strstate = "01";
            }
            int Intervaltime = Convert.ToInt32(AppSettingsHelper.Configuration["IntervalTime"]);

            string str = ladderid.ToString().PadLeft(2, '0') + "10003800020400" + strstate + Convert.ToString(Intervaltime / 1000, 16).ToUpper().PadLeft(4, '0');//"0" + stateFlg.ToString();
            byte[] jj = CRC16TOData(str);
            string data = ToHexs(jj, "");
            return data;
        }

    }
    #endregion
}
